{{^x-helidon-v3}}{{!

    Most non-body parameter values are handled largely the same regardless of their origin (path, query, cookie, header).
    Wrap a single-valued parameter in an Optional only if it is NOT declared as required; otherwise insist that it be present.

    The Helidon 4 API exposes path, query, and cookie values as Value objects but header values as Strings, so deal with
    them slightly differently.
}}{{#vendorExtensions.x-helidon-isMultipartFormParam}}{{^required}}{{^isContainer}}Optional.ofNullable({{/isContainer}}{{/required}}parts.get("{{baseName}}"){{^required}}{{^isContainer}}){{/isContainer}}{{/required}}{{!
}}{{/vendorExtensions.x-helidon-isMultipartFormParam}}{{!
}}{{^vendorExtensions.x-helidon-isMultipartFormParam}}{{^isFormParam}}request{{/isFormParam}}{{!
}}{{#isFormParam}}formParams{{/isFormParam}}{{!
}}{{#isPathParam}}.path()
                .pathParameters(){{!
}}{{/isPathParam}}{{!
}}{{#isQueryParam}}.query(){{!
}}{{/isQueryParam}}{{!
}}{{#isCookieParam}}.headers()
                .cookies(){{!
}}{{/isCookieParam}}{{!
}}{{#isHeaderParam}}.headers(){{!
}}{{/isHeaderParam}}{{!
  We have generated code to access the object from which we'll get either the first value or all the values given a name.
  Headers use "values" which accepts a HeaderName while the other objects use "all" which accepts a String to gather all of
  potentially multiple values. All types use "first" to retrieve only the first value with the name.
}}{{#isContainer}}{{!
}}{{#isHeaderParam}}
                .values(HeaderNames.create("{{baseName}}")){{!
}}{{/isHeaderParam}}{{!
}}{{^isHeaderParam}}
                .all("{{baseName}}"){{!
}}{{/isHeaderParam}}
                .stream(){{!
}}{{/isContainer}}{{!
}}{{^isContainer}}
                .first({{#isHeaderParam}}HeaderNames.create({{/isHeaderParam}}"{{baseName}}"{{#isHeaderParam}}){{/isHeaderParam}}){{!
}}{{^isHeaderParam}}
                .asOptional(){{/isHeaderParam}}{{!
}}{{#defaultValue}}
                .or(() -> Optional.of("{{defaultValue}}")){{/defaultValue}}{{!
}}{{/isContainer}}{{!
}}{{^isFile}}{{^isString}}
                .map({{>paramValueConverter}}){{!
}}{{/isString}}{{/isFile}}{{!
}}{{#isFormParam}}{{#isFile}}
                .map(HCollectors::decodeBinaryFormParam){{/isFile}}{{/isFormParam}}{{!
}}{{^vendorExtensions.x-helidon-hasEnumClass}}{{#isEnum}}
                .map(v -> validator.check("{{baseName}}",
                     v,
                     List.of({{#allowableValues}}{{#enumVars}}{{^-first}},
                             {{/-first}}{{{value}}}{{/enumVars}}{{/allowableValues}}))){{!
}}{{/isEnum}}{{/vendorExtensions.x-helidon-hasEnumClass}}{{!
}}{{#required}}{{^isContainer}}{{!
    We use orElse(null) here even if there is a default value that was applied (in string form) above. This allows us to plug
    in the default value earlier, as a string, before any conversion to the desired datatype, so we do not have to also convert
    the default value if we wanted to use it in the orElse.
}}
                .orElse(null){{/isContainer}}{{/required}}{{!
}}{{#isContainer}}{{!
}}{{#defaultValue}}
                .collect(HCollectors.toDefaultedList("{{defaultValue}}",
                                                    {{>paramValueConverter}})){{!
}}{{/defaultValue}}{{^defaultValue}}{{^isMap}}
                .collect(Collectors.to{{containerTypeMapped}}()){{/isMap}}{{!
}}{{#isMap}}
                // TODO - Developer must override this method and provide the correct mapping.
                .collect(HCollectors.noOpMap()){{/isMap}}{{!
}}{{/defaultValue}}{{!
}}{{/isContainer}}{{/vendorExtensions.x-helidon-isMultipartFormParam}};{{!
}}{{/x-helidon-v3}}